/*
 * Copyright 2009 Jiwei Xu (http://www.xujiwei.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

provide("CanvaShopView");

require("TinyJS.TinyView");
require("CanvaShopDoc");

require("Objects.FigureObj");

require("Undo.UndoManager");
require("Undo.ObjectDeleteCommand");
require("Undo.BatchCommand");

require("Tools.DrawTool");
require("Tools.PointTool");
require("Tools.RectTool");
require("Tools.LineTool");
require("Tools.MoveTool");
require("Tools.PolygonTool");
require("Tools.CurveTool");
require("Tools.CircleTool");
require("Tools.ImageTool");
require("Tools.ZoomTool");

CanvaShopView = Class(TinyView, (function() {
    var doc, THIS;

    var _currentZoom = 1;

    function drawGrid() {
        var ctx = THIS.Context;
        var oldlw = ctx.lineWidth;
        var size = THIS.GetViewSize();
        ctx.lineWidth = 1;
        for (var x = 20; x <= size.Width; x += 20) {
            ctx.fillRect(x, 0, 1, size.Height);
        }
        for (var y = 20; y <= size.Height; y += 20) {
            ctx.fillRect(0, y, size.Width, 1);
        }
        ctx.lineWidth = oldlw;
    }

    function draw() {
        var ctx = THIS.Context;
        var size = THIS.GetViewSize();
        ctx.clearRect(0, 0, size.Width, size.Height);
        //drawGrid(ctx);
        THIS.GetDocument().Draw(THIS);
    }

    function convertMousePosition(pt) {
        pt.X /= _currentZoom;
        pt.Y /= _currentZoom;

        return pt;
    }

    var offsetX, offsetY;

    function fixContext(ctx) {
        // * upgrade Firefox 3.0.x text rendering to HTML 5 standard
        if (!ctx.fillText && ctx.mozDrawText) {
            ctx.fillText = function(textToDraw, x, y, maxWidth) {
                ctx.translate(x, y);
                ctx.mozTextStyle = ctx.font;
                ctx.mozDrawText(textToDraw);
                ctx.translate(-x, -y);
            };
        }

        // * Setup measureText
        if (!ctx.measureText && ctx.mozMeasureText) {
            ctx.measureText = function(text) {
                if (ctx.font) ctx.mozTextStyle = ctx.font;
                var width = ctx.mozMeasureText(text);
                return { width: width };
            };
        }

        // * Setup html5MeasureText
        if (ctx.measureText && !ctx.html5MeasureText) {
            ctx.html5MeasureText = ctx.measureText;
            ctx.measureText = function(text) {
                var textMetrics = ctx.html5MeasureText(text);

                // fake it 'til you make it
                textMetrics.ascent = ctx.html5MeasureText("m").width;

                return textMetrics;
            };
        }

        // * for other browsers, no-op away
        if (!ctx.fillText) {
            ctx.fillText = function() {};
        }

        if (!ctx.measureText) {
            ctx.measureText = function() { return 10; };
        }

        return ctx;
    }

    return {
        Initialize : function(arg) {
            this.Base(arg);

            var canvas = this.ViewElement;
            this.Canvas = canvas;
            this.Context = fixContext(canvas.getContext("2d"));
            doc = arg.Document;
            THIS = this;

            DrawTool.SetCurTool(MoveTool);

            this.UndoManager = new UndoManager();
        },

        //////////////////////////////////////////
        /// Event Handlers

            OnMouseMove : function(e) {
                var tool = DrawTool.FindTool(DrawTool.GetCurTool());
                if (tool) {
                    tool.OnMouseMove(this, convertMousePosition(e));
                }

                TinyMQ.Publish("canvashop.mouse.move", e);
            },

            OnLButtonDown : function(e) {
                var tool = DrawTool.FindTool(DrawTool.GetCurTool());
                if (tool) {
                    tool.OnLButtonDown(this, convertMousePosition(e));
                }
            },

            OnLButtonUp : function(e) {
                var tool = DrawTool.FindTool(DrawTool.GetCurTool());
                if (tool) {
                    tool.OnLButtonUp(this, convertMousePosition(e));
                }
                this.ShowLayouts();
            },

            OnLButtonClick : function(e) {
                var tool = DrawTool.FindTool(DrawTool.GetCurTool());
                if (tool) {
                    tool.OnLButtonClick(this, convertMousePosition(e));
                }
            },

            OnLButtonDblClk : function(e) {
                var tool = DrawTool.FindTool(DrawTool.GetCurTool());
                if (tool) {
                    tool.OnLButtonDblClk(this, convertMousePosition(e));
                }
            },

        /// END Event Handlers
        //////////////////////////////////////////

        SetObjectStyles : function(obj) {
            var $ = function(id) {
                return document.getElementById(id);
            };
            obj.FillStyle = $("TxtFillColor").value;
            obj.StrokeStyle = $("TxtStrokeColor").value;
            obj.LineWidth = parseInt($("TxtLineWidth").value, 10);
            obj.IsFill = !!$("ChkIsFill").checked;
            obj.Alpha = parseInt($("TxtAlpha").value, 10);
            if (obj.Alpha != 100) {
                obj.Alpha %= 100;
            }
            obj.Alpha /= 100;
        },

        ResetStyles : function() {
            ctx.fillStyle = "black";
            ctx.storkeStyle = "black";
            ctx.lineWidth = 1;
            ctx.globalAlpha = 1;
            ctx.globalCompositeOperation = "source-over";
        },

        SetCursor : function(cursor) {
            this.Canvas.style.cursor = cursor;
        },

        ResetCursor : function() {
            this.Canvas.style.cursor = "default";
        },

        GetDocument : function() {
            return doc;
        },

        Update : function() {
            draw();
        },

        GetViewSize : function() {
            return {
                Width : this.Canvas.width,
                Height : this.Canvas.height
            };
        },

        ShowLayouts : function() {
            var layouts = this.GetDocument().GetLayouts();
            var control = document.getElementById("LayoutsList");
            control.innerHTML = "";
            for (var i = 0; i < layouts.length; ++i) {
                var li = document.createElement("LI");
                li.LayoutID = layouts[i].ID;
                li.innerHTML = (layouts[i].IsSelected ? "* " : " ") + layouts[i].Name;
                var img = document.createElement("IMG");
                img.width = img.height = 48;
                img.src = layouts[i].GetDataURL();
                li.insertBefore(img, li.firstChild);
                control.insertBefore(li, control.firstChild);
            }
        },

        Zoom : function(zoom) {
            var scale = zoom / _currentZoom;
            _currentZoom = zoom;
    
            this.Context.scale(scale, scale);
            this.Update();
            console.log('zoomin %f', _currentZoom);
            TinyMQ.Publish("canvashop.view.zoom", _currentZoom);
        },

        ZoomIn : function(rect) {
            var size = this.GetViewSize();
            var zoom = _currentZoom;

            if (rect.Width === 0 && rect.Height === 0) {
                zoom += zoom >= 1 ? 1 : 1/3;
            } else {
                var scaleX = size.Width / (rect.Width || 1),
                    scaleY = size.Height / (rect.Height || 1);

                zoom = Math.min(scaleX, scaleY);
            }

            this.Zoom(zoom);
        },

        ZoomOut : function(rect) {
            var size = this.GetViewSize();
            var zoom = _currentZoom;

            if (zoom > 1) {
                zoom -= (zoom % 1 || 1);
            } else {
            }

            this.Zoom(zoom);
        },

        ZoomOne : function(rect) {
        },

        ScrollTo : function(pt) {
        },

        //////////////////////////////////////////
        //  UI Control Messages

            OnButtonNewLayoutClick : function() {
                var layout = this.GetDocument().NewLayout();
                this.GetDocument().SelectLayout(layout);
                TinyMQ.Publish("canvashop.layouts.new", layout);
                this.ShowLayouts();
                this.Update();
            },

            OnLayoutsListClick : function(e) {
                var layout = e.target.LayoutID;
                this.GetDocument().SelectLayout(layout);
                this.ShowLayouts();
            },

            OnButtonToolMoveClick : function() {
                DrawTool.SetCurTool(MoveTool);
                console.info("Move tool");
            },

            OnButtonToolRectClick : function() {
                DrawTool.SetCurTool(RectTool);
                console.info("Rect tool");
            },

            OnButtonToolLineClick : function() {
                DrawTool.SetCurTool(LineTool);
                console.info("Line tool");
            },

            OnButtonToolPolygonClick : function() {
                DrawTool.SetCurTool(PolygonTool);
                console.info("Polygon tool");
            },

            OnButtonToolCurveClick : function() {
                DrawTool.SetCurTool(CurveTool);
                console.info("Curve tool");
            },

            OnButtonToolCircleClick : function() {
                DrawTool.SetCurTool(CircleTool);
                console.info("Circle tool");
            },

            OnButtonToolImageClick : function() {
                DrawTool.SetCurTool(ImageTool);
                console.info("Image tool");
            },

            OnButtonToolZoomClick : function() {
                DrawTool.SetCurTool(ZoomTool);
                console.info("ZoomTool tool");
            },

            OnButtonEditClearClick : function() {
                var doc = this.GetDocument();
                var cmd = new BatchCommand(doc.GetObjects().slice(0), {
                    Layout : doc.GetCurrentLayout(),
                    Command : ObjectDeleteCommand
                });
                this.UndoManager.Push(cmd);

                this.GetDocument().RemoveAll();
                this.Update();
            },

            OnButtonEditUndoClick : function() {
                this.UndoManager.Undo();
                this.Update();
            },

            OnButtonEditRedoClick : function() {
                this.UndoManager.Redo();
                this.Update();
            },

            OnButtonMoveObjUpClick : function() {
                var doc = this.GetDocument(),
                    objs = doc.GetSelectedObjects();
                for (var i = 0; i < objs.length; ++i) {
                    doc.MoveObjectUp(objs[i]);
                }

                this.Update();
            },

            OnButtonMoveObjTopClick : function() {
                var doc = this.GetDocument(),
                    objs = doc.GetSelectedObjects();
                for (var i = 0; i < objs.length; ++i) {
                    doc.MoveObjectTop(objs[i]);
                }

                this.Update();
            },

            OnButtonMoveObjDownClick : function() {
                var doc = this.GetDocument(),
                    objs = doc.GetSelectedObjects();
                for (var i = objs.length; i >= 0; --i) {
                    doc.MoveObjectDown(objs[i]);
                }

                this.Update();
            },

            OnButtonMoveObjBottomClick : function() {
                var doc = this.GetDocument(),
                    objs = doc.GetSelectedObjects();
                for (var i = objs.length; i >= 0; --i) {
                    doc.MoveObjectBottom(objs[i]);
                }

                this.Update();
            },

            __SelectItem : function(e) {
                var nodes = e.target.parentNode.parentNode.getElementsByTagName("button");
                for (var i = 0; i < nodes.length; ++i) {
                    nodes[i].className = "";
                }
                e.target.className = "selected";
                e.target.blur();
            },

            OnUpdateButtonToolMove : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolLine : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolRect : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolPolygon : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolCurve : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolCircle : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolImage : function(e) {
                this.__SelectItem(e);
            },

            OnUpdateButtonToolZoom : function(e) {
                this.__SelectItem(e);
            }

        /// END UI Control Message
        //////////////////////////////////////////
    };
})());
